home *** CD-ROM | disk | FTP | other *** search
- RCS_ID_C "$Id: rcmd.c,v 1.6 1993/10/08 00:02:44 ppessi Exp $";
- /*
- * rcmd.c --- remote login connection
- *
- * Author: ppessi <Pekka.Pessi@hut.fi>
- *
- * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
- * Helsinki University of Technology, Finland.
- * All rights reserved.
- *
- * Created : Tue May 18 01:59:25 1993 ppessi
- * Last modified: Wed Sep 22 19:57:07 1993 ppessi
- *
- * $Log: rcmd.c,v $
- * Revision 1.6 1993/10/08 00:02:44 ppessi
- * Fixed OOB handling when input buffer overflows.
- *
- * Revision 1.4 1993/08/12 06:19:13 jraja
- * Updated the email-address.
- *
- */
-
- #include <stdio.h>
- #include <string.h>
- #include "nifty.h"
- #include "amiga.h"
- #include "nio.h"
- #include <ctype.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/ioctl.h>
-
- struct Library *SocketBase;
-
- #if __SASC
- #include <proto/socket.h>
- #elif __GNUC__
- #include <inline/socket.h>
- #else
- #include <clib/socket_protos.h>
- #endif
- #include "rlogin.h"
-
- #define BUFSIZE 256
-
- char *username = NULL;
-
- int errno;
-
- BYTE IO_bit = -1;
- BYTE URG_bit = -1;
- ULONG SIGURG = 0;
-
- char okwinch = 0;
-
- struct winsize_packet winsize =
- { 0377, 0377, 's', 's', 0, 0, 0, 0 };
-
-
- long rresvport(long *alport);
-
- void
- CloseSocketBase(void)
- {
- if (SocketBase) CloseLibrary(SocketBase), SocketBase = NULL;
- if (IO_bit != -1) FreeSignal(IO_bit), IO_bit = -1;
- if (URG_bit != -1) FreeSignal(URG_bit), URG_bit = -1;
- }
-
- void
- rsendwsize(int s)
- {
- send(s, &winsize, sizeof(winsize), 0);
- }
-
- int
- rread(long s, char *buf, int length)
- {
- char tiop;
- int n = 0, m;
- int wasting = 0;
- char waste[BUFSIZE];
-
- for (;;) {
- /* We are at OOB data? */
- ioctl(s, SIOCATMARK, &m);
- if (m) {
- m = recv(s, &tiop, 1, MSG_OOB);
- if (m < 0) break;
-
- if (tiop & TIOCPKT_WINDOW) {
- /* Let server know about window size changes */
- okwinch = 1;
- rsendwsize(s);
- }
- /* Here we might want to handle other bits */
- if (tiop & TIOCPKT_FLUSHWRITE) {
- for (;;) {
- if (ioctl(s, SIOCATMARK, &m) < 0) {
- (void)perror(PROGNAME ": ioctl");
- n = -1;
- break;
- }
- if (m) break;
- n = recv(s, waste, sizeof (waste), 0);
- if (n <= 0) break;
- }
- n = 0;
- }
-
- /* SIGIO is not sent without this */
- #if USE_FIONBIO
- recv(s, waste, sizeof(waste), 0);
- #else
- recv(s, waste, 0, 0);
- #endif
- return n;
- }
- if ((m = recv(s, buf, length, 0)) < 0)
- break;
- if (wasting)
- continue;
- n += m; buf +=m; length -= m;
- if (length > 0) continue;
- wasting = 1; buf = waste; length = sizeof(waste);
- }
-
- return n;
- }
-
- /*
- * rcmd
- * Connect to the server using a privileged port
- */
- int
- rcmd(char **host, u_short rport,
- const char *locuser, const char *remuser, const char *term)
- {
- int s;
- struct sockaddr_in sin;
- struct in_addr saddr;
- char c;
- struct hostent *hp;
- int lport = IPPORT_RESERVED - 1;
- struct Task *pid = FindTask(NULL);
-
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = inet_addr(*host);
- if (sin.sin_addr.s_addr == (u_int)-1) {
- hp = gethostbyname(*host);
- if (hp == 0) {
- fputs(*host, stderr);
- fputs(": unknow target.\n", stderr);
- return (-1);
- }
- sin.sin_family = hp->h_addrtype;
- bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
- }
- sin.sin_port = rport;
-
- /* get a socket with a privileged port */
- s = rresvport(&lport);
- if (s < 0) {
- perror("rcmd: socket");
- return (-1);
- }
-
- ioctl(s, FIOSETOWN, (char*)&pid);
-
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- perror(*host);
- return (-1);
- }
-
- send(s, "", 1, 0);
- send(s, locuser, strlen(locuser)+1, 0);
- send(s, remuser, strlen(remuser)+1, 0);
- send(s, term, strlen(term)+1, 0);
- if (recv(s, &c, 1, 0) != 1) {
- perror(*host);
- goto bad;
- }
- if (c != 0) {
- while (recv(s, &c, 1, 0) == 1) {
- (void) fputc(c, stderr);
- if (c == '\n')
- break;
- }
- goto bad;
- }
- return s;
- bad:
- (void) CloseSocket(s);
- return (-1);
- }
-
- /*
- * Bind a socket with privileged port
- */
- long
- rresvport(long *alport)
- {
- struct sockaddr_in sin;
- int s;
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0)
- return (-1);
- for (;;) {
- sin.sin_port = htons((u_short)*alport);
- if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
- return (s);
- if (errno != EADDRINUSE) {
- (void) close(s);
- return (-1);
- }
- (*alport)--;
- if (*alport == IPPORT_RESERVED/2) {
- (void) close(s);
- errno = EAGAIN; /* close */
- return (-1);
- }
- }
- }
-